#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>
#include <pthread.h>
#include <sys/ipc.h>
#include <sys/msg.h>

#include "json_par.h"
#include "serial.h"
#include "server.h"
#include "logger.h"
#include "shared_data.h"
#include "udp_server.h"
#include "mqtt_cli.h"
#include "log.h"
#include "action_func.h"
#include "sql_func.h"
#include "json_data.h"

#include "fast_conble_func.h"
#include "device_control_data.h"

#include "rhythm_light.h"

#define NUM_SERIAL_PORTS 2
int serial_fd[NUM_SERIAL_PORTS];

#if 0
int main() {
    initLog("info.log");

    // 初始化共享数据的互斥锁
    if (pthread_mutex_init(&packet_mutex, NULL) != 0) {
        //perror("Mutex initialization failed");
        writeLog(ERROR,__FILE__,__func__,"Mutex initialization failed\n");
        exit(EXIT_FAILURE);
    }


    // 初始化和配置串口
    //ttyS0是485
    serial_fd[0] = initialize_serial("/dev/ttyS0", 9600, 8, 'N', 1); 
    serial_fd[1] = initialize_serial("/dev/ttyS2", 38400, 8, 'N', 1);
    // serial_fd[1] = initialize_serial("/dev/ttyS1", 38400, 8, 'N', 1);

    for (int i=0; i<NUM_SERIAL_PORTS;i++) {
        if (serial_fd[i] == -1) {
            writeLog(ERROR,__FILE__,__func__,"初始化串口/dev/ttyS%d错误\n", i);
            exit(EXIT_FAILURE);
        }
    }
    

    // 创建用于串口读取的线程
    pthread_t serial_threads[NUM_SERIAL_PORTS];
    for (int i = 0; i < NUM_SERIAL_PORTS; i++) {
        if (pthread_create(&serial_threads[i], NULL, read_serial, (void *)&serial_fd[i]) != 0) {
            //perror("创建串口线程错误");
            writeLog(ERROR,__FILE__,__func__,"创建串口线程错误\n");
            exit(EXIT_FAILURE);
        }
    }
    
    start_server();

    // 销毁互斥锁
    pthread_mutex_destroy(&packet_mutex);

    closeLog();
    return 0;
}
#endif

#if 0
int main(int argc, char** argv)
{
    if (InitUdpServer("192.168.3.172", 8888) == -1) {
        // 处理初始化失败的情况
        fprintf(stderr, "Failed to initialize UDP server\n");
        return EXIT_FAILURE;
    }

    // 数据包解析处理
    MsgProcess();

    // 关闭UDP服务器并释放资源
    DeinitUdpServer();
    return 0;
}
#endif

int test2()
{
    uint8_t value[40] = {0};
    printf("test2\n");
    printf("%s\n", devList_p);
    int ret = devList_getAttribute("00000000000000000000ec0bf1008879", "devname", value);
    printf("%d, %s\n", ret, value);
}

int test1()
{
    // 创建一个 JSON 对象
    cJSON *root = cJSON_CreateObject();

    // 向 JSON 对象添加键值对
    cJSON_AddStringToObject(root, "name", "John");
    cJSON_AddNumberToObject(root, "age", 25);

    // 创建一个数组
    cJSON *array = cJSON_CreateArray();

    // 向数组添加元素
    cJSON_AddItemToArray(array, cJSON_CreateString("Apple"));
    cJSON_AddItemToArray(array, cJSON_CreateString("Banana"));
    cJSON_AddItemToArray(array, cJSON_CreateString("Orange"));

    // 将数组添加到 JSON 对象
    cJSON_AddItemToObject(root, "fruits", array);

    // 将 JSON 对象转换为 JSON 文本
    char *jsonText = cJSON_Print(root);

    // 打印生成的 JSON 文本
    printf("Generated JSON:\n%s\n", jsonText);

    // 释放内存
    cJSON_free(jsonText);
    cJSON_Delete(root);

    return 0;
}
int test()
{
    // 创建一个 JSON 对象
    cJSON *data = cJSON_CreateObject();

    // 向对象中添加键值对
    cJSON_AddItemToObject(data, "id", cJSON_CreateString(""));

    // 创建一个嵌套的 JSON 对象
    cJSON *config = cJSON_CreateObject();

    // 将 JSON 对象转换为 JSON 文本
    char *jsonText = cJSON_Print(data);

    // 打印生成的 JSON 文本
    printf("Generated JSON:\n%s\n", jsonText);

    // 释放 JSON 对象和文本内存
    cJSON_Delete(data);
    free(jsonText);

    return 0;
}

void attr_check(void)
{
    uint8_t attr[2048] = {0};
    int ret;
    log_info("attr_check");
    ret = devList_getAttribute("00000000000000000000ec0bf1008879", "devname", attr);
    printf("%d\n", ret);
    printf("%s\n", attr);
}
// 独立线程执行，键盘触发处理
void *keyTrigger(void *args)
{
    char key = 0;
    uint8_t mask1[13] = {0};
    mask1[0] = 1;
    uint8_t con[6] = {0};
    uint8_t con1[6] = {0x80 + 0x32, 0, 0, 0, 0xff, 0};
    uint8_t te[] = "test";
    int ret;
    while (1)
    {
        key = getchar();
        cJSON *categoryJson = cJSON_CreateObject();
        switch (key)
        {
        case 'a': // 获取属性
            attr_check();
            break;
        case 'b': // 设备类型
            cJSON_AddStringToObject(categoryJson, "blecatetory", "");
            list_getAttributeJson(devList_Json, "shortaddr", "1", &(categoryJson->child));
            log_info("%s", cJSON_Print(categoryJson));
            break;
        case 'm':
            mqtt_publish_test();
            break;
        case 'r': // 短地址为1的设备上报
            FastConbleTriggerDataReport(0, 10, mask1);

            break;
        case 's': // 短地址为1的设备上报
            if (!OneDevTriggerDataReport(10))
            {
                if (!OneDevReportResult_wait())
                {
                    uint8_t *p = NULL;
                    uint16_t dataLen = 0;
                    p = reportMsg_buffer;
                    dataLen = reportMsg_len;
                    printf("msg [ ");
                    for (uint16_t i = 0; i < dataLen + 1; i++)
                    {
                        printf("%02X ", *(p + i));
                    }
                    printf("]\n");
                    // }
                    report_sem_post();
                }
                else
                {
                    report_sem_post();
                }
            }
            break;
        case 'c': // 控制短地址为1的设备开启
            // con[0] = 0x80;
            // FastConbleShortAddrControl(1, con, 1);
            // light_control_Bright(1, 50);
            con[0] = 0xFF;
            con[4] = 0x0;  // W
            con[5] = 0xFF; // C
#if 1
            for (int i = 0; i < 3; i++)
            {
                FastConbleGroupControl(205, 0x2aa8, con, 6); // 0x2ba8
                controlGroupFlag = 1;
                struct timespec req = {0, 200 * 1000000};
                nanosleep(&req, NULL);
                if (controlGroupFlag == 0)
                {
                    printf("ack\n");
                    break;
                }
            }
            for (int i = 0; i < 3; i++)
            {
                FastConbleGroupControl(204, 0x2ba8, con, 6); // 0x2ba8
                controlGroupFlag = 1;
                struct timespec req = {0, 800 * 1000000};
                nanosleep(&req, NULL);
                if (controlGroupFlag == 0)
                {
                    printf("ack\n");
                    break;
                }
            }
            for (int i = 0; i < 3; i++)
            {
                FastConbleGroupControl(203, 0x2ba8, con, 6); // 0x2ba8
                controlGroupFlag = 1;
                struct timespec req = {0, 800 * 1000000};
                nanosleep(&req, NULL);
                if (controlGroupFlag == 0)
                {
                    printf("ack\n");
                    break;
                }
            }
            for (int i = 0; i < 3; i++)
            {
                FastConbleGroupControl(206, 0x2ba8, con, 6); // 0x2ba8
                controlGroupFlag = 1;
                struct timespec req = {0, 800 * 1000000};
                nanosleep(&req, NULL);
                if (controlGroupFlag == 0)
                {
                    printf("ack\n");
                    break;
                }
            }
#endif
#if 0
            for (int i = 0; i < 5; i++)
            {
                FastConbleGroupControl(205, 0x2aa8, con, 6); // 0x2ba8
                if (controlResult_Sem_timedwait() == 0)
                // if (controlResult_cond_wait() == 0)
                {
                    printf("ack\n");
                    break;
                }
            }
            for (int i = 0; i < 5; i++)
            {
                FastConbleGroupControl(204, 0x2ba8, con, 6); // 0x2ba8
                if (controlResult_Sem_timedwait() == 0)
                // if (controlResult_cond_wait() == 0)
                {
                    printf("ack\n");
                    break;
                }
            }
            for (int i = 0; i < 5; i++)
            {
                FastConbleGroupControl(203, 0x2ba8, con, 6); // 0x2ba8
                if (controlResult_Sem_timedwait() == 0)
                // if (controlResult_cond_wait() == 0)
                {
                    printf("ack\n");
                    break;
                }
            }
            for (int i = 0; i < 5; i++)
            {
                FastConbleGroupControl(206, 0x2ba8, con, 6); // 0x2ba8
                if (controlResult_Sem_timedwait() == 0)
                // if (controlResult_cond_wait() == 0)
                {
                    printf("ack\n");
                    break;
                }
            }
#endif
            // FastConbleGroupControl(203, 0x2ba8, con, 6); // 0x2ba8
            // FastConbleGroupControl(204, 0x2ba8, con, 6); // 0x2ba8
            break;
        case 'd': // 控制短地址为1的设备关闭
            con[0] = 0x00;
            // FastConbleShortAddrControl(1, con, 1);
            for (int i = 0; i < 3; i++)
            {
                FastConbleGroupControl(205, 0x2aa8, con, 1); // 0x2ba8
                controlGroupFlag = 1;
                struct timespec req = {0, 800 * 1000000};
                nanosleep(&req, NULL);
                if (controlGroupFlag == 0)
                {
                    printf("ack\n");
                    break;
                }
            }
            for (int i = 0; i < 3; i++)
            {
                FastConbleGroupControl(204, 0x2ba8, con, 1); // 0x2ba8
                controlGroupFlag = 1;
                struct timespec req = {0, 800 * 1000000};
                nanosleep(&req, NULL);
                if (controlGroupFlag == 0)
                {
                    printf("ack\n");
                    break;
                }
            }
            for (int i = 0; i < 3; i++)
            {
                FastConbleGroupControl(203, 0x2ba8, con, 1); // 0x2ba8
                controlGroupFlag = 1;
                struct timespec req = {0, 800 * 1000000};
                nanosleep(&req, NULL);
                if (controlGroupFlag == 0)
                {
                    printf("ack\n");
                    break;
                }
            }
            for (int i = 0; i < 3; i++)
            {
                FastConbleGroupControl(206, 0x2ba8, con, 1); // 0x2ba8
                controlGroupFlag = 1;
                struct timespec req = {0, 800 * 1000000};
                nanosleep(&req, NULL);
                if (controlGroupFlag == 0)
                {
                    printf("ack\n");
                    break;
                }
            }
            // FastConbleGroupControl(205, 0x2aa8, con, 1);
            // FastConbleGroupControl(204, 0x2ba8, con, 1);
            // FastConbleGroupControl(203, 0x2ba8, con, 1);
            break;
        case 'e':
            rhythm_timer_set();
            break;
        case 'f':
            rhythm_stop();
            break;
        case 't':
            /* code */
            printf("keyTrigger\r\n");
            // test2();
            // list_update_stateData(NULL, 0, 2);
            printf("%s\n", cJSON_Print(devList_Json));
            break;
        case 'u': // 手动触发URL
            FastConbleUrlRequest();
            break;

        case '1': // 回家场景
            // FastConbleSceneControl(196614);
            con[0] = 0x80;
            FastConbleShortAddrControl(8, con, 1);
            break;
        case '2': // 柔和场景
            // FastConbleSceneControl(196610);
            con[0] = 0x00;
            FastConbleShortAddrControl(8, con, 1);
            break;
        case '3': // 场景控制
            FastConbleGroupControl(196, 0x2ba8, con1, 6);
            break;
        case '4':
            rhythm_timer_set();
            break;
        default:
            break;
        }
    }
}

#define FILE_SIZE 1024 * 1024
// main2
int main2()
{
    int ret;
    // FILE *file = fopen("devJson.txt", "r");
    FILE *file = fopen("groupJson.txt", "r");
    if (file == NULL)
    {
        printf("Failed to open file.\n");
        return 1;
    }

    int fileSize = 0;
    fseek(file, 0L, SEEK_END);
    fileSize = ftell(file);
    fseek(file, 0L, SEEK_SET);
    // char buffer[FILE_SIZE];
    char *buffer = (char *)calloc(1, fileSize);
    // while (fgets(buffer, sizeof(buffer), file) != NULL)
    // {
    //     // printf("%s\n", buffer);
    // }
    // 读取文件数据到缓冲区中
    size_t result = fread(buffer, 1, fileSize, file);
    if (result != fileSize)
    {
        perror("读取文件失败");
        fclose(file);
        free(buffer);
        return 1;
    }
    fclose(file);

    char *jsonString = buffer;
    // 解析JSON字符串
    cJSON *root = cJSON_Parse(jsonString);
    if (root == NULL)
    { // 出错处理
        const char *error_ptr = cJSON_GetErrorPtr();
        if (error_ptr != NULL)
        {
            printf("Error before: %s\n", error_ptr);
        }
        cJSON_Delete(root);
        return 1;
    }
    // printf("%s\n", cJSON_Print(root));
    devList_Json = root;
    groupList_Json = root;

#if 1 // 群组列表
    uint8_t ch[20] = {0};
    uint16_t groupID = 205;
    snprintf(ch, sizeof(ch), "%d", groupID);
    cJSON *blecatetoryJson = NULL;
    cJSON *index = NULL;
    index = cJSON_CreateObject();
    cJSON_AddStringToObject(index, "groupId", ch);
    blecatetoryJson = cJSON_CreateObject();
    cJSON_AddStringToObject(blecatetoryJson, "blecatetory", "");
    // ret = checkGroupJson(ch, blecatetoryJson);
    list_getOneAttrJson(groupList_Json, index, &blecatetoryJson);
    if (ret != 0)
    {
        fprintf(stderr, "check group json failed\n");
    }
    // memset(ch, 0, sizeof(ch));
    // strcpy(ch, blecatetoryJson->child->valuestring);
    log_info("group test:%s", blecatetoryJson->child->valuestring);
    log_info("group type:%d", ret);
    cJSON_Delete(blecatetoryJson);
#endif
#if 0 // 设备列表
    // uint8_t *id = "00000000000000000000ec0bf1008879";  //开关 短10
    uint8_t *id = "00000000000000000000ec0bf10b5c82"; // 射灯1  短1
    uint16_t deviceType = 0;
    uint16_t addr = 0;
    ret = list_getDeviceType(id, &deviceType);
    // printf("%d\n", ret);
    ret = list_getShortAddr(id, &addr);
    // printf("%d\n", ret);

    cJSON *index = NULL;
    cJSON *filter = NULL;
    cJSON *config = NULL;
    cJSON *_config = NULL;
    index = cJSON_CreateObject();
    filter = cJSON_CreateArray();
    cJSON_AddStringToObject(index, "CF_RegionId", "3");
    cJSON_AddStringToObject(index, "spid", "0000000000000000000000002ba80000");
    cJSON_AddItemToArray(filter, index);

    _config = cJSON_CreateObject();
    config = cJSON_CreateArray();
    cJSON_AddStringToObject(_config, "CF_DeviceId", "");
    cJSON_AddStringToObject(_config, "CF_RegionId", "");
    cJSON_AddItemToArray(config, _config);
    hz_list_device_get(NULL, filter, config);
    // attributeToSerName(config);
    printf("%s\n", cJSON_Print(config));
    
    // printf("%s\n", buffer);
#endif

#if 0 // 键值转换

    uint8_t *id = "00000000000000000000ec0bf1008879"; // 开关 短10
    uint8_t *spid = "2ba8";
    cJSON *index = NULL;
    index = cJSON_CreateObject();
    cJSON_AddStringToObject(index, "id", id);
    cJSON_AddStringToObject(index, "CF_ProductId", spid);
    // jsonValueToSerStr(index->child->next);
    jsonValueToMqttIteration(index);
    jsonValueToMqttIteration(index);
    jsonValueToMqttIteration(index);
    printf("%s\n", cJSON_Print(index));
#endif

#if 0 // 群组列表

    cJSON *_element = cJSON_CreateObject();
    cJSON_AddStringToObject(_element, "roomId", "");
    cJSON *index = cJSON_CreateObject();
    cJSON_AddStringToObject(index, "groupId", "198");
    ret = list_getOneAttrJson(groupList_Json, index, &_element);

    printf("%s\n%d\n", cJSON_Print(_element), ret);

#endif
}
// main3
int main()
{
    readData();
}


// main1
int main1(int argc, char *argv[])
{
    pthread_t keyTrigger_thread;
    pthread_create(&keyTrigger_thread, NULL, keyTrigger, NULL);

    rhythm_timer_create();
    UrlRequest_timer_create();
    UrlRequest_timer_set();
    // 线程同步
    // 信号量
    report_sem_init();
    reportMsg_create();
    controlResult_Sem_init();

    // 文件夹路径
    const char *folder_path = "./logs";

    printf("%s\n", STRINGIFY(functionPointers[0]));

    int total_action_cnt = sizeof(functionPointers) / sizeof(HzFunctionPointer);
    printf("total_action_cnt %d\n", total_action_cnt);

    // 获取当前时间
    time_t rawtime;
    struct tm *timeinfo;
    char buffer[80];

    time(&rawtime);
    timeinfo = localtime(&rawtime);

    strftime(buffer, sizeof(buffer), "%Y%m%d%H%M%S", timeinfo);

    if (access(folder_path, F_OK) != 0)
    {
        if (mkdir(folder_path, 0777) != 0)
        {
            perror("Error creating folder");
            return 1;
        }
    }

    // 创建log文件
    char file_path[100];
    snprintf(file_path, sizeof(file_path), "%s/%s.log", folder_path, buffer);

    FILE *file = fopen(file_path, "ab");
    if (file == NULL)
    {
        perror("Error creating file");
        return 1;
    }

    // 初始化LOG
    log_set_level(LOG_TRACE);
    log_set_quiet(0);

    log_add_fp(file, LOG_DEBUG);

    log_debug("debug");
    log_info("info");
    log_warn("warn");

    /*初始化数据库*/
    InitDatabase("./gateway.db");

    char *host = NULL;
    if (argc < 2)
    {
        // host = "192.168.3.199";
        host = "brambling-device.chinafsl.com";
        log_info("use default ip: %s\n", host);
    }
    else
    {
        host = argv[1];
        log_info("use ip: %s\n", host);
    }
    g_test_mosq = connect_to_mqtt_server(host);
    if (!g_test_mosq)
    {
        log_error("connect to server %s failed\n", host);
        exit(0);
    }

    // if (InitUdpServer("192.168.3.44", 8888) == -1)
    if (InitUdpServer("0.0.0.0", 8888) == -1)
    {
        // 处理初始化失败的情况
        perror("Failed to initialize UDP server");
        return EXIT_FAILURE;
    }

    // udp数据包解析处理，创建线程
    StartUdpMsgHandle();

    mosquitto_loop_forever(g_test_mosq, -1, 1);

    mosquitto_destroy(g_test_mosq);
    mosquitto_lib_cleanup();
    // 关闭UDP服务器并释放资源
    DeinitUdpServer();
    return 0;
}
